package com.fy.fyspace.common.aop;

import com.fy.fyspace.common.annotation.PerformanceMonitor;
import com.fy.fyspace.model.vo.monitor.PerformanceRecordVO;
import com.fy.fyspace.service.PerformanceMonitorService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 性能监控切面
 * 拦截带有@PerformanceMonitor注解的方法，记录性能数据
 * 
 * @author fy
 * @since 2024-01-01
 */
@Aspect
@Component
@Slf4j
public class PerformanceMonitorAspect {

    @Resource
    private PerformanceMonitorService performanceMonitorService;

    /**
     * 环绕通知，拦截带有@PerformanceMonitor注解的方法
     */
    @Around("@annotation(com.fy.fyspace.common.annotation.PerformanceMonitor)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        // 获取注解
        PerformanceMonitor monitor = method.getAnnotation(PerformanceMonitor.class);
        
        // 检查是否启用监控
        if (!monitor.enabled()) {
            return joinPoint.proceed();
        }
        
        // 生成记录ID
        String recordId = UUID.randomUUID().toString();
        
        // 获取监控名称
        String monitorName = monitor.value();
        if (monitorName.isEmpty()) {
            monitorName = method.getDeclaringClass().getSimpleName() + "." + method.getName();
        }
        
        // 获取请求信息
        String requestUri = "";
        String requestMethod = "";
        String clientIp = "";
        String userAgent = "";
        
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                requestUri = request.getRequestURI();
                requestMethod = request.getMethod();
                clientIp = getClientIp(request);
                userAgent = request.getHeader("User-Agent");
            }
        } catch (Exception e) {
            log.warn("获取请求信息失败", e);
        }
        
        // 记录开始时间
        long startTime = System.currentTimeMillis();
        LocalDateTime startDateTime = LocalDateTime.now();
        
        // 记录请求参数
        String requestParams = "";
        if (monitor.logParams()) {
            try {
                Object[] args = joinPoint.getArgs();
                if (args != null && args.length > 0) {
                    StringBuilder params = new StringBuilder();
                    for (int i = 0; i < args.length; i++) {
                        if (i > 0) params.append(", ");
                        params.append(args[i]);
                    }
                    requestParams = params.toString();
                }
            } catch (Exception e) {
                log.warn("记录请求参数失败", e);
            }
        }
        
        Object result = null;
        boolean hasException = false;
        String exceptionType = "";
        String exceptionMessage = "";
        
        try {
            // 执行原方法
            result = joinPoint.proceed();
            return result;
            
        } catch (Exception e) {
            hasException = true;
            exceptionType = e.getClass().getSimpleName();
            exceptionMessage = e.getMessage();
            throw e;
            
        } finally {
            // 记录结束时间
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            
            // 记录响应结果
            String responseResult = "";
            if (monitor.logResult() && !hasException) {
                try {
                    responseResult = result != null ? result.toString() : "null";
                } catch (Exception e) {
                    log.warn("记录响应结果失败", e);
                }
            }
            
            // 检查是否为慢查询
            boolean slowQuery = executionTime > monitor.slowThreshold();
            
            // 记录异常信息
            if (hasException && monitor.logException()) {
                log.warn("方法执行异常 - monitorName: {}, executionTime: {}ms, exception: {}", 
                        monitorName, executionTime, exceptionMessage);
            }
            
            // 记录慢查询
            if (slowQuery) {
                log.warn("检测到慢查询 - monitorName: {}, executionTime: {}ms, threshold: {}ms", 
                        monitorName, executionTime, monitor.slowThreshold());
            }
            
            // 创建性能记录
            PerformanceRecordVO record = new PerformanceRecordVO();
            record.setRecordId(recordId);
            record.setMonitorName(monitorName);
            record.setDescription(monitor.description());
            record.setClassName(method.getDeclaringClass().getName());
            record.setMethodName(method.getName());
            record.setRequestUri(requestUri);
            record.setRequestMethod(requestMethod);
            record.setClientIp(clientIp);
            record.setUserAgent(userAgent);
            record.setRequestParams(requestParams);
            record.setResponseResult(responseResult);
            record.setStartTime(startDateTime);
            record.setEndTime(LocalDateTime.now());
            record.setExecutionTime(executionTime);
            record.setSlowThreshold(monitor.slowThreshold());
            record.setSlowQuery(slowQuery);
            record.setHasException(hasException);
            record.setExceptionType(exceptionType);
            record.setExceptionMessage(exceptionMessage);
            record.setCreateTime(LocalDateTime.now());
            
            // 保存性能记录
            try {
                performanceMonitorService.savePerformanceRecord(record);
            } catch (Exception e) {
                log.error("保存性能记录失败", e);
            }
        }
    }
    
    /**
     * 获取客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
} 